#include "../Elogs/bitlog.h"
#include <vector>
#include <thread>
#include <chrono>

//参数解释:
//logger_name:日志器名称
//thr_count:线程数量
//msg_count:日志总数量
//msg_len:日志长度

void bench(const std::string &logger_name, size_t thr_count, size_t msg_count, size_t msg_len)
{
    // 1. 获取日志器
    log::Logger::ptr logger = log::getLogger(logger_name); // 通过日志器名字获取指定唯一日志器
    if (logger.get() == nullptr)
        return;
    std::cout << "测试日志: " << msg_count << "条,总大小" << (msg_count * msg_len) / 1024 << "KB\n";
    // 2. 组织指定长度的日志消息
    std::string msg(msg_len - 1, 'A');
    // 3. 创建指定数量的线程
    std::vector<std::thread> threads;
    std::vector<double> const_arry(thr_count);
    size_t msg_prt_thr = msg_count / thr_count; // 总日志数量/线程数量等于每个线程要输出的日志数量
    for (int i = 0; i < thr_count; i++)
    {
        threads.emplace_back([&, i]()
                             {
            //4. 线程函数内部计时开始
            auto start = std::chrono::high_resolution_clock::now();
            //5. 开始循环写日志
            for(int j=0;j<msg_prt_thr;j++)
            {
                logger->fatal("%s",msg.c_str());
            }
        //6. 线程函数内部结束计时
        auto end =std::chrono::high_resolution_clock::now();
        std::chrono::duration<double> cost = end-start;
        const_arry[i] =cost.count();
        std::cout <<"\t线程" << i<<": "<<"\t输出数量" << msg_prt_thr << " ,耗时:"<< cost.count() <<"s"<<std::endl; });
    }
    for (int i = 0; i < thr_count; i++)
    {
        threads[i].join(); // 等待线程退出
    }
    // 7. 计算总耗时:在多线程中，每个线程多会花费时间,但是线程是并发处理，统计处耗时最高的那个线程
    double max_time = const_arry[0];
    for (int i = 0; i < thr_count; i++)
    {
        max_time = max_time < const_arry[i] ? const_arry[i] : max_time;
    }
    size_t msg_per_sec = msg_count / max_time; // 总日志数量/最大耗时等于吞吐量
    size_t size_per_sec = (msg_count * msg_len) / (max_time * 1024);
    // 8. 进行输出打印
    std::cout << "\t总耗时: " << max_time << "s\n"; 
    std::cout << "\t每秒输出日志数量: " << msg_per_sec << "条\n";
    std::cout << "\t每秒输出的日志大小: " << size_per_sec << "KB\n";
}
void sync_bench()
{
    std::unique_ptr<log::LoggerBuilder> builder(new log::GlobalLoggerBuilder());
    builder->buildLoggerName("sync_logger");
    builder->buildLoggerFormatter("%m%n");
    builder->buildLoggerType(log::LoggerType::LOGGER_SYNC);
    builder->buildSink<log::FileSink>("./logfile/sync.log");
    builder->build();
    //同步
    bench("sync_logger",3,1000000,100);
}

void async_bench()
{
    std::unique_ptr<log::LoggerBuilder> builder(new log::GlobalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildLoggerFormatter("%m%n");
    builder->buildLoggerType(log::LoggerType::LOGGER_ASYNC);
    builder->buildEnableUnSafeAsync();
    builder->buildSink<log::FileSink>("./logfile/async.log");
    builder->build();
    //异步
    bench("async_logger",1,1000000,100);
}

int main()
{
    //sync_bench();
    async_bench();
    return 0;
}

//同步单线程与多线程
//结论:单线程耗时比多线程短,因为锁冲突比较严重

//异步单线程与多线程
//单线程耗时比多线程长,因为只需向缓冲区,而拷贝数据进行实际落地,由CPU和内存决定
